#!/usr/bin/env python
# -*- coding:utf-8 -*-
import ConfigParser
import hashlib
import time
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

def wrapper_login(func):    #定义装饰器，用于购物网站和信用卡网站登录，func是指被装饰的函数；
    def login():    #添加的功能函数
        CardInfoFile=ConfigParser.ConfigParser()    #加载ConfigParser方法
        CardInfoFile.read('info.txt')   #读入文件到内存，以便后续操作
        CardRealNumber=CardInfoFile.get('login','cardnum')  #读取用户的正确信用卡号
        CardRealPass=CardInfoFile.get('login','cardpass')   #读取用户的正确密码
        while True:
            UserInputCardNumber=raw_input("please input your card number:") #用户输入卡号
            UserInputCardPass=raw_input("please input card password:")#start把用户输入的密码转换成md5
            hash=hashlib.md5()  #调用md5加密方法
            hash.update(UserInputCardPass)  #将用户密码转成md5的hash格式
            UserInputCardPass=hash.hexdigest()#end
            FailLoginNumber=CardInfoFile.getint('login','failnum')#登录次数失败了会变，所以放在循环里；
            if UserInputCardNumber==CardRealNumber :    #判断输入的hashcode是不是和正确密码的匹配
                if FailLoginNumber>=3:  #如果登录次数已经超过3次，禁止登录；
                    print "Login failure Number is too many!"
                    break
                if UserInputCardPass==CardRealPass: #密码匹配对了
                    func()  #执行被装饰函数
                else:
                    print 'Password invalid!'   #密码不匹配
                    CardInfoFile.set('login','failnum',str(FailLoginNumber+1))
                    CardInfoFile.write(open('info.txt','w'))    #写入失败次数
            else:
                print "CreditCard Number is invalid!"   #卡号不正确
    return login    #返回login函数体

def FetchRecord():  #定义查询消费记录，后面的主体函数会调取
    with open('record')as fr:   #文件描述符
        for record in fr:   #读取每行值
            print record.strip()    #去掉换行符打印

def WriteRcord(*args):  #定义消费记录的写文件操作，消费、取钱、还款等都会用到。
    ConsumeRecord=time.strftime('%Y-%m-%d')+",%s%s,%s元\n"%args  #消费记录的文件格式，传入3个参数；
    with open('record','a')as fa:   #追加文件描述符
        fa.write(ConsumeRecord) #写入消费记录文件

def FetchBalance():     #定义查询余额函数
    InfoFile=ConfigParser.ConfigParser()    #ConfigParser方法读取文件
    InfoFile.read('info.txt')
    return InfoFile.getfloat('login','balance') #获取这个用户下的余额值

def GetCash():  #定义取现函数
    Balance=FetchBalance()  #先查询余额
    UserGetCashNum=float(raw_input("你现在的余额是%s,输入提现金额："%Balance))    #提现金额
    if UserGetCashNum*1.05>Balance: #判断是否余额不足
        print "取不出那么多!"
        return  #如果余额够支取，退出函数
    Balance=float(Balance-UserGetCashNum*1.05)  #计算支取后的余额
    InfoFile=ConfigParser.ConfigParser()        #用ConfigParser方法更新此卡余额
    InfoFile.read('info.txt')
    InfoFile.set("login","balance",Balance)
    InfoFile.write(open("info.txt","w"))    #写入文件
    print "取现成功！账户余额%s元" % FetchBalance()
    WriteRcord("提现","",UserGetCashNum)  #追加写入记录

def repay():    #定义还款
    Balance=FetchBalance()  #获取余额
    UserRepayment=float(raw_input("要还款金额："))    #还款金额变量定义
    Balance=Balance+UserRepayment   #计算还款后余额
    InfoFile=ConfigParser.ConfigParser()    #用ConfigParser方法更新此卡余额
    InfoFile.read('info.txt')
    InfoFile.set('login',"balance",Balance)
    InfoFile.write(open("info.txt","w"))    #写入文件
    print "还款成功！账户余额%s元" % FetchBalance()
    WriteRcord("还款","",UserRepayment)   #追加写入记录文件

'''
默认是用login账户登录，新建了一个login1用户，把钱转给他，也就是多了一个section，都是login1的信息；
处理info.txt文件用ConfigParser方法，如果login1的姓名和账号都能对上，就转账；
ConfigParser读取文件中login1的余额，把转账金额加上，用write方法写入文件，login的减去相应金额；
'''
def transacount():  #定义转账
    TransToUser=raw_input("收款人姓名：")
    TransToCard=raw_input("收款人账号：")
    TransAcount=float(raw_input("转账金额："))
    InfoFile=ConfigParser.ConfigParser()
    InfoFile.read('info.txt')
    CardNum1=InfoFile.get(TransToUser,'cardnum')
    Balance1=InfoFile.getfloat(TransToUser,'balance')
    if InfoFile.has_section(TransToUser):
        if TransToCard==CardNum1:
            Balance=FetchBalance()-TransAcount
            Balance1+=TransAcount
            InfoFile.set('login','balance',Balance)
            InfoFile.set(TransToUser,"balance",Balance1)
            InfoFile.write(open("info.txt","w"))
            print("转账成功，您的余额是%s元"%FetchBalance())
            WriteRcord("转账给",TransToUser,TransAcount)
        else:
            print "姓名或卡号不正确！"
    else:
        print("没有这个用户")

@wrapper_login  #封装信用卡网站，加入验证功能
def creditcardweb():    #信用卡网站主函数
    while True:
        creditweblist=["查询余额","取现","还款","转账","交易记录","退出"]
        for num,web in enumerate(creditweblist,1):
            print num,web       #打印操作列表
        UserSelect=raw_input("输入选择：")
        if UserSelect=='1':
            print FetchBalance()
        elif UserSelect=='2':
            GetCash()
        elif UserSelect=='3':
            repay()
        elif UserSelect=='4':
            transacount()
        elif UserSelect=='5':
            FetchRecord()
        elif UserSelect=='6':
            break
        else:
            print("输入错误!")

@wrapper_login  #封装购物网站，加入验证功能
def shopping(): #定义购物网站主函数
    ShopInfoFile=ConfigParser.ConfigParser()
    ShopInfoFile.read('info.txt')   #也是用section和option格式设计购物列表
    GoodsList=ShopInfoFile.options('shoplist')  #获取商品列表
    Balance=ShopInfoFile.getfloat('login','balance')
    while True:
        print "您的信用卡可用消费：%d元" % Balance
        for num,goods in enumerate(GoodsList,1):    #打印商品价目表
            print num,goods,'售价:%s元'% ShopInfoFile.get('shoplist',goods)    #如：1 ipad 3588元
        print "0 退出"
        UserSelectNum=int(raw_input("选择商品编号购买:"))
        if UserSelectNum==0:break
        UserSelectGoods=GoodsList[UserSelectNum-1]  #按下标取商品
        UserSelectGoodsPrice=ShopInfoFile.getfloat('shoplist',UserSelectGoods)  #按商品名称取价格
        if Balance-UserSelectGoodsPrice >=0:    #看钱够不够
            print "购买成功!"
            Balance=Balance-UserSelectGoodsPrice    #扣钱
            WriteRcord("购买",UserSelectGoods,UserSelectGoodsPrice)
        else:
            print "购买失败，余额不足！"
    ShopInfoFile.set('login','balance',Balance)
    ShopInfoFile.write(open('info.txt','w'))    #写入消费记录文件

while True:
    WebList=["信用卡网站","购物网站","退出"]
    for num,options in enumerate(WebList,1):
        print num,options
    UserSelect=raw_input("输入选择：")
    if UserSelect=='1':
        print "欢迎进入信用卡网站，请登录："
        creditcardweb()
    elif UserSelect=='2':
        print "欢迎进入购物网站，请登录："
        shopping()
    elif UserSelect=='3':
        print ("欢迎再次光临！")
        break
    else:
        print "输入错误"



#信用卡账单发送，每月30日
date=time.strftime('%Y-%m-%d')  #获取当前日期
DateList=date.split('-')    #将年月日切割成列表，以备判断。

def bill(): #生成账单内容
    InfoFile=ConfigParser.ConfigParser()    #ConfigParser方法读取文件
    InfoFile.read('info.txt')
    Balance=InfoFile.getfloat('login','balance')    #账户余额
    Maxline=InfoFile.getfloat('login','maxline')    #最大信用额
    Billmoney=Maxline-Balance   #应还款额=最大信用额-账户余额
    Bill='您%s年%s月的信用卡账单已生成，应还款%d元。'%(DateList[0],DateList[1],Billmoney)
    return Bill #返回账单内容，发邮件时调用；

def email():
    msg = MIMEText(bill(), 'plain', 'utf-8')    #将账单内容当做邮件内容
    msg['From'] = formataddr(["xx银行信用卡中心",'CreditCardtest123@126.com'])
    msg['To'] = formataddr(["测试账户login",'42136639@qq.com'])
    msg['Subject'] = "信用卡账单"

    server = smtplib.SMTP("smtp.126.com", 25)
    server.login("CreditCardtest123@126.com", "******")
    server.sendmail('CreditCardtest123@126.com', ['42136639@qq.com',], msg.as_string())
    server.quit()

if DateList[-1]==30:    #如果当前日期是30日，就发送账单邮件通知用户；
    email()